import os
import gc
import time
from multiprocessing import Process, Manager
from flask import Flask, request,json
import cv2
import uuid
from threading import Thread
from time import sleep

app = Flask(__name__)
# 向共享缓冲栈中写入数据:
def write(stack, cam, top: int) -> None:
    print('Process to write: %s' % os.getpid())
    cap = cv2.VideoCapture(cam)
    while True:
        _, img = cap.read()
        if _:
            stack.append(img)
            # 每到一定容量清空一次缓冲栈
            # 利用gc库，手动清理内存垃圾，防止内存溢出
            if len(stack) >= top:
                del stack[::2]
                gc.collect()

# 在缓冲栈中读取数据:
def read(stack,id) -> None:  # 提醒返回值是一个None
    print("stack:",stack,id)
    print('Process to read: %s' % os.getpid())
    index = 0
    fourcc = cv2.VideoWriter_fourcc('P', 'I', 'M', '2')  # MPEG-4.2
    # 下面的格式根据不同情况选择
    # fourcc = cv2.VideoWriter_fourcc('P','I','M','1')  # MPEG-1
    # fourcc = cv2.VideoWriter_fourcc('M','J','P','G') # motion-jpeg codec
    # fourcc = cv2.VideoWriter_fourcc('D', 'I', 'V', '3') # MPEG-4.3 codec
    # fourcc = cv2.VideoWriter_fourcc('P', 'I', 'M', '2')  # MPEG-4.2
    # fourcc = cv2.VideoWriter_fourcc('D', 'I', 'V', 'X') # MPEG - 4    codec
    # fourcc = cv2.VideoWriter_fourcc('U', '2', '6', '3') # H263    codec
    # fourcc = cv2.VideoWriter_fourcc('I', '2', '6', '3') # H263I   codec
    # fourcc = cv2.VideoWriter_fourcc('F', 'L', 'V', '1') # FLV1 codec

    out = cv2.VideoWriter('video_out.mpg', fourcc, 6.3, (1280, 720))
    start_time = time.time()
    x = 1  # displays the frame rate every 1 second
    counter = 0
    print("开始逐帧读取")
    while True:
        # print("正在读取第%d帧：" %index)
        if len(stack) >= 10:
            frame = stack.pop(0)
            # 逐帧保存为图片
            resize_frame = cv2.resize(frame, (720, 480), interpolation=cv2.INTER_AREA)
            cv2.imwrite("./static/img/%03d.jpg" % id,resize_frame)
            index = index + 1;
            # 计算fps
            counter += 1
            if (time.time() - start_time) > x:
                # print("FPS: ", counter / (time.time() - start_time))
                counter = 0
                start_time = time.time()
            key = cv2.waitKey(1) & 0xFF
            if key == ord('q'):
                break
        else:
            continue
    out.release()
    cv2.destroyAllWindows()


def videoAsync(path,id):
    # 父进程创建缓冲栈，并传给各个子进程：
    q = Manager().list()
    print("pw,pr:",pw,pr)
    pw = Process(target=write, args=(q, path, 100))  # 海康威视视频流地址
    pr = Process(target=read, args=(q, id))
    pw.start()
    pr.start()
    pr.join()
    pw.terminate()

def playWay(path,id):
    cap = cv2.VideoCapture(path)
    ret, frame = cap.read()
    cv2.destroyAllWindows()
    cap.release()
    while ret:
        ret, frame = cap.read();
        cv2.imwrite('./static/img/videoPlay.jpg', frame)  # 存储为图像
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cv2.destroyAllWindows()
    cap.release()


def asyncWay(f):
    def wrapper(*args, **kwargs):
        thr = Thread(target=f, args=args, kwargs=kwargs)
        thr.start()
    return wrapper


@asyncWay
def asyncVideo(path,id):
    sleep(0.001)
    # videoAsync(path,id);
    playWay(path,id);


@app.route("/video", methods=['get'])
def video():
    path = request.args.to_dict().get('url')
    id = uuid.uuid1();
    asyncVideo(path,id);
    return json.dumps({"code": 200, "url":id ,"type":"jpg", "msg": "请求视频成功"});



if __name__ == '__main__':
    app.run()


